<?php
namespace modules\game\services\method;

class ThreePStraight extends IMethod{
		
	public static $_name = __CLASS__;

	//检测牌
	public function test(Array $testPoker){
		$this->_testNum = count($testPoker);
		$this->_testPoker = $testPoker;
		if($this->_testNum  < 6 || $this->_testNum % 3) return false;
		$num = $this->_testNum / 3;
		$flag = true;
		for( $i = 1 ; $i <= $num ; ++$i){
			$n = ($i - 1) * 3;
			$m = $n + 1;
			$k = $n + 2;
			$flag = floor($this->_testPoker[$n]/10) === floor($this->_testPoker[$m]/10) 
			&& floor($this->_testPoker[$m]/10) === floor($this->_testPoker[$k]/10);
			if(!$flag) break;
		}
		return $flag;
	}
	/**
	 * 牌分段，顺子归块
	 * exp: [3,4,5,6,7,9,10,11,12,13,16]
	 * return [
	 * 		[3,4,5,6,7],
	 * 		[9,10,11,12,13],
	 * 		[16]
	 * ];
	 */
	public function straightSplit(Array $pokerNum){
		$flag = 0;
		$data = $chunk = [];
		foreach($pokerNum as $one){
			if(($flag + 1) === $one){
				$chunk[] = $one;
			}else{
				if($chunk){
					$data[] = $chunk;
				}
				$chunk = [$one];
			}
			$flag = $one;
		}
		$data[] = $chunk;
		return $data;
	}
	/**
	 * 出牌策略
	 * @param  array $userPoker 用户当前的牌,已模块
	 * @return array 出的牌 | bool 没有此类型的牌，不出
	 */
	public function out($userPoker){//出牌
		$valid = array_filter($userPoker,function($a){
			return count($a) === 3;
		});
		if(count($valid) < 2) return false;
		$keys = array_keys($valid);
		$keys = $this->straightSplit($keys);
		$use = [];
		foreach($keys as $one){
			if(count($one) >= 2){//优先取第一个符合要求的
				$use = $one;
				break;
			}
		}
		if(empty($use)) return false;
		$map = [];
		$scale = current($use) - 1;
		$nums = count($use);
		for($i = 1 ; $i <= $nums ; ++$i){
			$map[] = $i + $scale;
		}
		if(!array_diff($map,$use)){//顺子
			$poker = [];
			foreach($use as $one){
				$poker = array_merge($poker,$valid[$one]);//注意连对  数组 包裹
			}
			//检测
			if($this->test($poker)){
				return $poker;
			}
		}
		return false;
	}
	/**
	 * 压牌策略
	 * @param  array $userPoker     我目前的牌
	 * @param  array $opponentPoker 当前需要被压的牌
	 * @param  bool  $intense  是否尽力压牌  true是  or false 否
	 * @return array  出牌 | bool: false 压不住
	 */
	public function suppress($userPoker,$opponentPoker,$intense){
		$valid = array_filter($userPoker,function($a){
			return count($a) === 3;
		});
		$userKeys = array_keys($valid);
		$oppoKeys = array_keys($opponentPoker);
		$nums = count($opponentPoker);
		$data = $this->straightSplit($userKeys);

		foreach($data as $possible){
			if(($len = count($possible)) >= $nums){
				if($possible[$len-1] > $oppoKeys[$nums-1]){
				//顺子最后一张大于 要压的牌
					if($possible[0] > $oppoKeys[0]){//首张牌大于
						$useKeys = array_slice($possible,0,$nums);						
					}else{//首张牌小于
						$useKeys = array_map(function($a){
							return ++$a;
						},$oppoKeys);
					}
					$useVals = [];
					foreach($useKeys as $useKey){
						$useVals = array_merge($useVals,$valid[$useKey]);//注意连对  数组 包裹
					}
					if($this->test($useVals)){
						return $useVals;
					}
				}
			}
		}
		if($intense){//强制拆牌出牌
			return $this->forceSuppress($userPoker,$opponentPoker);
		}
		return false;
	}
}